﻿// Spun AJAX Framework
// Copyright (C) 2008 Blake Hegerle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spun.Controllers;
using Spun;
using Formality.Logic.Game;
using Formality.Logic;
using Spun.Models.Sequences;
using Formality.FormalSystem;

namespace Formality.Server
{
    public class FormalityController : IController
    {
        public FormalityController()
        {
            // Spun setup
            GameModel = App.New<IGame>("Game");
            GameModel.Goal = App.New<IResult>();

            GameModel.Submissions = SubmissionList = new ListSequence<ISubmission>();
            GameModel.Results = ResultList = new ListSequence<IResult>();

            Input = App.New<IInput>("Input");
            //new Watch(Input, "Value", V => Submit(V as string));

            // Formality setup
            Engine = new Engine();
            Player = new Player("Blake");
            ActiveGame = new ActiveGame(Engine, Player);

            UpdateState();
        }

        private void UpdateState()
        {
            if (ActiveGame.Goal != null)
                Map(ActiveGame.Goal, GameModel.Goal);
            Map(ActiveGame.Premises, ResultList);

            foreach (var Sub in ActiveGame.Submissions)
                Map(Sub);
        }

        [Operation]
        public void Submit(string Input)
        {
            Map(ActiveGame.Submit(Input));
        }

        private ISubmission Map(Submission Submission)
        {
            var iSub = App.New<ISubmission>();
            iSub.Result = App.New<IResult>();

            Map(Submission.Sentence, iSub.Result);

            GameModel.Status = Submission.Response.ToString();

            switch (Submission.Response)
            {
                case Submission.ResponseType.Accepted:
                    iSub.Accepted = Submission.Response == Submission.ResponseType.Accepted;
                    SubmissionList.Add(iSub);
                    break;
                case Submission.ResponseType.Finished:
                case Submission.ResponseType.Proved:
                    UpdateState();
                    break;
                case Submission.ResponseType.Rejected:
                    SubmissionList.Add(iSub);
                    break;
            }

            return iSub;
        }

        private static void Map(Sentence Sentence, IResult Result)
        {
            Result.Id = Sentence.Id;
            Result.Sentence = Sentence.ToString();
        }

        private static void Map(IEnumerable<Sentence> Premises, ListSequence<IResult> Results)
        {
            var pArray = Premises.ToArray();

            for (var i = Results.Count; i < pArray.Length; i++)
            {
                var Result = App.New<IResult>(t =>
                    {
                        t.Sentence = pArray[i].ToString();
                        t.Id = pArray[i].DisplayId;
                    });

                Results.Add(Result);
            }
        }

        private IGame GameModel;
        private IInput Input;

        private ListSequence<ISubmission> SubmissionList;
        private ListSequence<IResult> ResultList;

        private Player Player;
        private ActiveGame ActiveGame;
        private Engine Engine;
    }
}
